package com.xd.core.openapi.controller;

import cn.hutool.core.lang.hash.Hash;
import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.xd.common.ascept.ResponseNotIntercept;
import com.xd.common.util.IpUtils;
import com.xd.common.util.RSAUtils;
import com.xd.core.business.entity.IncomingInfo;
import com.xd.core.business.mapper.IncomingInfoMapper;
import com.xd.core.business.mapper.RepaymentScheduleMapper;
import com.xd.core.business.service.IOutInfoService;
import com.xd.core.company.entity.CompanyRsa;
import com.xd.core.company.mapper.CompanyIpMapper;
import com.xd.core.company.mapper.CompanyMapper;
import com.xd.core.company.mapper.CompanyRsaMapper;
import com.xd.core.debt.vo.EarlyRepayVo;
import com.xd.core.openapi.dto.*;
import com.xd.core.openapi.service.OpenapiService;
import com.xd.core.openapi.vo.IncomingIdVo;
import com.xd.core.system.entity.SysUser;
import com.xd.core.system.vo.Resp;
import com.xd.core.openapi.vo.BillDetailVo;
import com.xd.core.openapi.vo.OutDetailVo;
import com.xd.core.product.service.IProductService;
import com.xd.core.product.vo.ProductVo1;
import com.xd.core.system.vo.Resp;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

//开放接口
@Slf4j
@RestController
@RequestMapping("/open/apiv1")
public class OpenapiController {
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private CompanyIpMapper companyIpMapper;
    @Autowired
    private CompanyRsaMapper companyRsaMapper;
    @Autowired
    private OpenapiService openapiService;
    @Autowired
    private IncomingInfoMapper incomingInfoMapper;
    @Autowired
    private IOutInfoService iOutInfoService;
    @Autowired
    private RepaymentScheduleMapper repaymentScheduleMapper;
    @Autowired
    private IProductService iProductService;


    /*
     * 1.响应：绑卡唯一码
     * 2.并给客户发送短信验证码
     * */
    @ResponseNotIntercept
    @ApiOperation("开放接口-预绑卡")
    @PostMapping("/readySign")
    public Resp readySign(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) throws Exception {
        OpenReadySignDto check = check(openapiBaseDto, request, OpenReadySignDto.class);
        checkIncoming(check.getIncomingId(), openapiBaseDto.getAppid());
        String s = openapiService.readySign(check);
        HashMap<String, String> map = new HashMap<>();
        map.put("uniqueCode", s);
        return Resp.success(map);
    }

    @ResponseNotIntercept
    @ApiOperation("开放接口-确认绑卡")
    @PostMapping("/confirmSign")
    public Resp confirmSign(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) throws Exception {
        OpenConfirmSignDto check = check(openapiBaseDto, request, OpenConfirmSignDto.class);
        checkIncoming(check.getIncomingId(), openapiBaseDto.getAppid());
        openapiService.confirmSign(check);
        return Resp.success();
    }

    @ResponseNotIntercept
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("开放接口-直接支付(手动代扣)")
    @PostMapping("/singlePay")
    public Resp singlePay(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) throws Exception {
        OpenSinglePayDto check = check(openapiBaseDto, request, OpenSinglePayDto.class);
        checkIncoming(check.getIncomingId(), openapiBaseDto.getAppid());
        openapiService.singlePay(check, openapiBaseDto.getAppid());
        return Resp.success();
    }
    @ResponseNotIntercept
    @ApiOperation("线下转账（创建订单）")
    @PostMapping("/offlinePay")
    public Resp offlinePay(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) throws Exception {
        OPenOfflinePayDto check = check(openapiBaseDto, request, OPenOfflinePayDto.class);
        checkIncoming(check.getIncomingId(), openapiBaseDto.getAppid());
        openapiService.offlinePay(check,openapiBaseDto.getAppid());
        return Resp.success();
    }

    @ResponseNotIntercept
    @ApiOperation("开放接口-填写贷款资料")
    @PostMapping("/fillInformation")
    public Resp fillInformation(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) {
        OpenIncomingInfoDto openIncomingInfoDto = check(openapiBaseDto, request, OpenIncomingInfoDto.class);
        openIncomingInfoDto.setCompanyId(openapiBaseDto.getAppid());
        Integer i = openapiService.fillInformation(openIncomingInfoDto);
        HashMap<String, Integer> map = new HashMap<>();
        map.put("incomingId", i);
        return Resp.success(map);
    }


    @ResponseNotIntercept
    @ApiOperation("开放接口-签署合同")
    @PostMapping("/doContract")
    public Resp doContract(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) {
        OpenapiContractDto openapiContractDto = check(openapiBaseDto, request, OpenapiContractDto.class);
        checkIncoming(openapiContractDto.getIncomingId(), openapiBaseDto.getAppid());
        openapiService.doContract(openapiContractDto);
        return Resp.success();
    }

    @ResponseNotIntercept
    @ApiOperation("开放接口-获取公司下产品")
    @PostMapping("/getProduct")
    public Resp getProducts(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) {
        check(openapiBaseDto,request,null);
        List<ProductVo1> productVoList = iProductService.getProductVoList(openapiBaseDto.getAppid());
        return Resp.success(productVoList);
    }

    @ResponseNotIntercept
    @ApiOperation("开放接口-放款")
    @PostMapping("/goLending")
    public Resp goLending(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) {
        IncomingIdVo incomingIdVo = check(openapiBaseDto, request, IncomingIdVo.class);
        Integer incomingId = incomingIdVo.getIncomingId();
        checkIncoming(incomingId, openapiBaseDto.getAppid());
        String s = iOutInfoService.goLending(incomingIdVo);
        HashMap<String, String> map = new HashMap<>();
        map.put("orderNo", s);//放款订单号
        return Resp.success(map);
    }

    @ResponseNotIntercept
    @ApiOperation("开放接口-放款详情")
    @PostMapping("/lendingDetail")
    public Resp lendingDetail(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) {
        IncomingIdVo incomingIdVo = check(openapiBaseDto, request, IncomingIdVo.class);
        Integer incomingId = incomingIdVo.getIncomingId();
        checkIncoming(incomingId, openapiBaseDto.getAppid());
        OutDetailVo outDetailVo = iOutInfoService.lendingDetail(incomingId);
        return Resp.success(outDetailVo);
    }

    @ResponseNotIntercept
    @ApiOperation("开放接口-账单详情")
    @PostMapping("/billDetail")
    public Resp billDetail(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) {
        IncomingIdVo incomingIdVo = check(openapiBaseDto, request, IncomingIdVo.class);
        Integer incomingId = incomingIdVo.getIncomingId();
        checkIncoming(incomingId, openapiBaseDto.getAppid());
        List<BillDetailVo> billDetailVos = repaymentScheduleMapper.billDetail(incomingId);
        if (CollectionUtils.isEmpty(billDetailVos))
            return Resp.success("账单未生成");
        return Resp.success(billDetailVos);
    }


    @ResponseNotIntercept
    @ApiOperation("提前还款")
    @PostMapping("/earlyRepayment")
    public Resp earlyRepayment(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request) {
        OpenEarlyRepaymentDto check = check(openapiBaseDto, request, OpenEarlyRepaymentDto.class);
        checkIncoming(check.getIncomingId(), openapiBaseDto.getAppid());
        EarlyRepayVo vo = openapiService.earlyRepayment(check);
        return Resp.success(vo);
    }

    @ResponseNotIntercept
    @ApiOperation("还款记账")
    @PostMapping("/bookkeeping")
    public Resp bookkeeping(@RequestBody OpenapiBaseDto openapiBaseDto, HttpServletRequest request){
        OpenapiKeepBookingDto check = check(openapiBaseDto, request, OpenapiKeepBookingDto.class);
        checkIncoming(check.getIncomingId(), openapiBaseDto.getAppid());
        openapiService.bookkeeping(check);
        return Resp.success();
    }

    @ApiOperation("测试加密接口")
    @PostMapping("/ceshirsa")
    public String ceshirsa(@RequestBody JSONObject  json){
        String jsonString = JSONObject.toJSONString(json);
        return RSAUtils.publicEncrypt(jsonString, "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyUd/FojQt2YUf41Ukvta9OPnLUwKFkWX/8PFMsIzXZPpXKNYRiAXwETyHvL0bT6SumNSFLPCKySfwPhD5HmGcXmKxOOriJ6ePlNeogjBvWXA7/Fylf71fJhLKEXN4TmsuDiwCyeHoBDx0x0kSIriLq4bXiUQs3UczfDsDgAw3cZf8LyHZDCZbJ9AyU1zEeNYlUr2UTTB23sDRK87vTQWqz18pA36IX7KyHnifpduZ+nf5zQRI2oruRvh27MsCZp7yc8m5GL+4zl5fur8Uu2WYcDlecvGrvnfk+XiJOSGkOkpHfEyM27lzxdbss0jfiOrgnsTjtOCP3PlJOvGKvg/xwIDAQAB");
    }

    @ResponseNotIntercept
    @ApiOperation("测试放款回调")
    @PostMapping("/ceshifkhd")
    public String ceshifkhd(@RequestBody JSONObject  json){
        log.info("放款回调"+json.toJSONString());
        return "OK";
    }

    @ResponseNotIntercept
    @ApiOperation("测试回款回调")
    @PostMapping("/ceshihkhd")
    public String ceshihkhd(@RequestBody JSONObject  json){
        log.info("回款回调"+json.toJSONString());
        return "OK";
    }


    //校验企业
    private <T> T check(OpenapiBaseDto openapiBaseDto, HttpServletRequest request, Class<T> clazz) {
        Integer appid = openapiBaseDto.getAppid();
        String data = openapiBaseDto.getData();
        String clientIpAddr = IpUtils.getClientIpAddr(request);
        String isOpenStatus = companyMapper.selectById(appid).getIsOpenStatus();
        //验证是否开通开放接口
        if (isOpenStatus.equals("0"))
            throw new RuntimeException("该企业未开通该功能");
        //验证ip是否允许访问
        List<String> companyIps = companyIpMapper.selectIps(appid);
        if (!companyIps.contains(clientIpAddr))
            throw new RuntimeException("ip未开通白名单");
        if (StringUtils.isBlank(data))
            return null;
        //验证密钥
        CompanyRsa companyRsa = companyRsaMapper.selectById(appid);
        return RSAUtils.decryptToClass(companyRsa.getPriKey(), data, clazz);
    }

    //校验进件是否属于该企业
    private void checkIncoming(Integer incomingId, Integer appid) {
        IncomingInfo incomingInfo = incomingInfoMapper.selectById(incomingId);
        if (incomingInfo == null || !incomingInfo.getCompanyId().equals(appid) || incomingInfo.getIncomingType().equals("1"))
            throw new RuntimeException("客户不存在");
    }

}
